package lq

import "gitee.com/hasika/gotool/container"

type MapQuery[K comparable, V any] struct {
	rangeFunc func(v container.MapVisitor[K, V])
}

func NewMapQuery[K comparable, V any](m map[K]V) MapQuery[K, V] {
	return MapQuery[K, V]{
		rangeFunc: func(v container.MapVisitor[K, V]) {
			for k, value := range m {
				if !v(k, value) {
					break
				}
			}
		},
	}
}

func NewMapQueryFromIterable[K comparable, V any](m container.MapIterable[K, V]) MapQuery[K, V] {
	return MapQuery[K, V]{
		rangeFunc: func(v container.MapVisitor[K, V]) {
			m.Iterate(v)
		},
	}
}

func (q MapQuery[K, V]) Predict(acceptor container.MapAcceptor[K, V]) MapQuery[K, V] {
	return MapQuery[K, V]{
		rangeFunc: func(v container.MapVisitor[K, V]) {
			q.rangeFunc(func(key K, value V) bool {
				if acceptor(key, value) {
					return v(key, value)
				}
				return true
			})
		},
	}
}

func (q MapQuery[K, V]) KeyToList() ListQuery[K] {
	return ListQuery[K]{
		rangeFunc: func(v container.ListVisitor[K]) {
			q.rangeFunc(func(key K, value V) bool {
				return v(key)
			})
		},
	}
}

func (q MapQuery[K, V]) ValueToList() ListQuery[V] {
	return ListQuery[V]{
		rangeFunc: func(v container.ListVisitor[V]) {
			q.rangeFunc(func(key K, value V) bool {
				return v(value)
			})
		},
	}
}

func (q MapQuery[K, V]) AllKeys() []K {
	keys := make([]K, 0, 2)
	q.rangeFunc(func(key K, value V) bool {
		keys = append(keys, key)
		return true
	})
	return keys
}

func (q MapQuery[K, V]) AllValues() []V {
	values := make([]V, 0, 2)
	q.rangeFunc(func(key K, value V) bool {
		values = append(values, value)
		return true
	})
	return values
}

func (q MapQuery[K, V]) All() map[K]V {
	ret := make(map[K]V, 8)
	q.rangeFunc(func(key K, value V) bool {
		ret[key] = value
		return true
	})
	return ret
}

func (q MapQuery[K, V]) Iterate(visitor container.MapVisitor[K, V]) {
	q.rangeFunc(visitor)
}
